﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using FazaDemo.BL.InterfaceDomain;
using FazaDemo.PL.Mapping;
using FazaDemo.ViewModels;

namespace FazaDemo.PL.Wpf
{
    class SuppleTabContentFiller : ITabContentFiller
    {

        private const string SupInfoHeader = "Справочная информация";

        private const string AddSearchConds = "Добавление и условия поиска";

        private IList<string> butContents = new List<string>
            {"F5", "+", "Условия"};

        private readonly Thickness _defButttonThickness;

        private Grid _gridInnerSupple;

        private readonly IList<DataGridFactory> _dgridFactories;

        private TabControl _tabCtrlInner;

        private IList<RoutedEventHandler> _topButtonsEvents;

        private IList<TabItem> _tabs;

        private readonly IContainerElementMapper<NavCondElement, NavElementViewModel> _contMapper;

        private readonly ILowToTopMapper<NavigatorCondition, NavPageViewModel> _mapper;

        private readonly WorkArea _workArea;

        public SuppleTabContentFiller(WorkArea workArea)
        {
            _defButttonThickness = new Thickness {Left = 5, Top = 3};
            IDgridCustomizer customizer = new SuppleDgridCustomizer();
            _dgridFactories = new List<DataGridFactory>
            {
                new DistrictGridFactory(customizer), 
                new PlaceGridFactory(customizer), 
                new StreetGridFactory(customizer)
            };
            _topButtonsEvents =
            new List<RoutedEventHandler>
            {
                On_SearchClick, 
                On_AddButtonClick, 
                On_CondsClick
            };
            _contMapper = new ContainerElementMapper<NavCondElement, NavElementViewModel>();
            _mapper = new LowToTopMapper<NavigatorCondition, NavPageViewModel>();
            _workArea = workArea;
        }

        public void Fill(IList<TabItem> tabs)
        {
            _tabs = tabs;
            var tabContTypes = new List<string> {"district", "place", "street"};
            for (int i = 0; i < _dgridFactories.Count; i++)
            {
                var grid = new Grid();
                grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
                _tabCtrlInner = GenerateInnerTabCtrl();
                var tabSupInfo = GetTabSupInfo();
                FillInnerTabItems(tabSupInfo, _dgridFactories[i], tabContTypes[i]);
                grid.Children.Add(_tabCtrlInner);
                _tabs[i].Content = grid;
            }
        }

        private TabItem GetTabSupInfo()
        {
            return _tabCtrlInner.Items.GetItemAt(0) as TabItem;
        }

        private TabControl GenerateInnerTabCtrl()
        {
            var tabCtrlInner = new TabControl();
            tabCtrlInner.Items.Add(new TabItem { Header =  SupInfoHeader});
            tabCtrlInner.Items.Add(new TabItem { Header = AddSearchConds });
            return tabCtrlInner;
        }

        private void FillInnerTabItems(TabItem tabSupInfo, DataGridFactory dgridFactory, string tabContType)
        {
            DefineSupGridMarkup();
            SetTopButtons(tabContType);
            dgridFactory.Create(_gridInnerSupple);
            tabSupInfo.Content = _gridInnerSupple;
        }

        private void DefineSupGridMarkup()
        {
            _gridInnerSupple = new Grid();
            _gridInnerSupple.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
            _gridInnerSupple.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto });
            _gridInnerSupple.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
            _gridInnerSupple.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
            _gridInnerSupple.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
            _gridInnerSupple.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
        }

        private void SetTopButtons(string tabContType)
        {
            for (int i = 0; i < butContents.Count(); i++)
            {
                SetOneButton(butContents[i], i, _topButtonsEvents[i], tabContType);
            }
        }

        private void SetOneButton(string content, int coordIndex, 
            RoutedEventHandler eventAction, string tabContType)
        {
            _gridInnerSupple.Children.Add(new Button
            {
                Name = (tabContType + coordIndex),
                Content = content,
                Margin = _defButttonThickness, 
            });
            var newButton = _gridInnerSupple.Children[coordIndex] as Button;
            if (newButton != null)
            {
                newButton.Click += eventAction;
                Grid.SetRow(newButton, 0);
                Grid.SetColumn(newButton, coordIndex);   
            }
        }


        private void On_AddButtonClick(object sender, RoutedEventArgs e)
        {
            var recButton = sender as Button;
            if (recButton != null)
            {
                Tuple<TabItem, string> tabItemInfo = PreInsertTab(recButton);
                var addBuilderFactory = new AddPanelBuilderFactory();
                AddPanelBuilder addBuilder = addBuilderFactory.Create(tabItemInfo.Item2);
                addBuilder.Build(tabItemInfo.Item1);
            }
        }

        private void On_SearchClick(object sender, RoutedEventArgs e)
        {

        }

        private void On_CondsClick(object sender, RoutedEventArgs e)
        {
            var condButton = sender as Button;
            if (condButton != null)
            {
                Tuple<TabItem, string> tabItemInfo = PreInsertTab(condButton);
                var ecqFactory = new EcqFactory();
                int ecq = ecqFactory.GetEcqIndex(tabItemInfo.Item2);
                var receiver = new NavDataReceiver();
                NavigatorCondition navCond = receiver.Get(ecq);
                NavPageViewModel navViewModel = GenerateViewModel(navCond);
                var builder = new NavigatorBuilder(navViewModel);
                builder.Build(tabItemInfo.Item1, _workArea);
            }
        }

        private Tuple<TabItem, string> PreInsertTab(Button recButton)
        {
            var indexFactory = new TabIndexFactory();
            string tabType = recButton.Name.Substring(0, recButton.Name.Length - 1);
            int tabIndex = indexFactory.Get(tabType);
            var gridInner = _tabs[tabIndex].Content as Grid;
            var tabContInner = gridInner.Children[0] as TabControl;
            TabItem tabItemInner = tabContInner.Items.GetItemAt(1) as TabItem;
            tabItemInner.Content = null;
            return new Tuple<TabItem,string>(tabItemInner, tabType);
        }

        private NavPageViewModel GenerateViewModel(NavigatorCondition navCond)
        {
            IEnumerable<NavElementViewModel> elemModels = _contMapper.MapFrom(navCond.CondElements);
            NavPageViewModel model = _mapper.MapFrom(navCond);
            model.NavArea = elemModels;
            return model;
        }

    }
}